package hui.com.authority;

import hui.com.util.RedisUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 权限注释，内容。信息处理
 */
@Aspect
@Component
public class AuthorityAuthorizationAspect {
    @Before("@annotation(authority) && execution(* *(..))")
    public void authorize(JoinPoint joinPoint, Authority authority) throws Throwable {

        // 获取钥匙
        String key = getKeyFromRequest();
        // 从Redis中获取钥匙对应的值
        UsersLogEntity redisValue = (UsersLogEntity) getRedisValueByKey(key);

        // 找不到token对应的值
        if (redisValue==null){
            throw  AuthorityException.keyExpired();
        }
        // 验证是否有权限
        if (!hasPermission(redisValue, authority.value(),key)) {
            throw new IllegalAccessException("Access denied: Insufficient permissions");
        }
    }


    /**
     *  获取前端请求接口访问的数据
     * @return
     */
    private String getKeyFromRequest() {
        // 从请求中获取钥匙的逻辑
        // ...
        //获取HttpServletRequest
        // 通过 RequestContextHolder 获取当前请求的 HttpServletRequest
        // 这需要在 Spring Boot 的配置类中开启对 RequestContextListener 的支持
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();

        return request.getHeader("Authorization");
    }

    private Object getRedisValueByKey(String key) {
        // 从Redis中获取钥匙对应的值的逻辑
        // ...
        if (key!=null){
            return RedisUtil.getValue(key); // 从Redis中获取到的key值
        }
        throw AuthorityException.keyNULL();
    }

    /**
     *
     * @param redisValue getRedisValueByKey方法返回的值
     * @param requiredPermission 权限注解的值
     * @return true表示运行访问该接口。false（没有false，不过不满足条件直接throw。）
     */
    private boolean hasPermission(Object redisValue, String requiredPermission,String token) {
        // 根据值的一部分来判断是否有权限的逻辑
        // ...
        //System.out.println(redisValue+"======"+requiredPermission);
        UsersLogEntity usersLog = (UsersLogEntity) redisValue;

        if (usersLog.getPermsArray()!=null){
            //System.out.println("Ashifou;"+usersLog.isExpired());
            //是否过期
            if (usersLog.isExpired()){
                //确认过期，进行删除，然后反馈前端
                RedisUtil.deleteValue(token);
                throw AuthorityException.keyExpired();
            }
            // 拥有管理员权限则直接通过
            if (Arrays.asList(usersLog.getPermsArray()).contains("admin")){
                return true;
            }

            // 是否拥有该接口的正常权限
            for(String perms:usersLog.getPermsArray()){

                if (isPrefix(perms,requiredPermission)) { // 满足条件允许访问接口
                    return true;
                }
            }
        }

        throw AuthorityException.keyMismatch();
//        return false;

//        if (redisValue.isEmpty() && requiredPermission.isEmpty()){ //前端上传的为空，同时权限设置的是空（无聊的人才使用空注释，这个判断纯粹防无聊的人）
//            throw AuthorityException.keyERR();
//        }else if (requiredPermission.isEmpty()){ // 权限设置的是空（无聊的人才使用空注释，这个判断纯粹防无聊的人）
//            throw AuthorityException.keyERR();
//        } else if (redisValue.isEmpty()) { //前端上传的钥匙为空，不满足条件
//            throw AuthorityException.keyNULL();
//        } else if (isPrefix(redisValue,requiredPermission)) { // 满足条件允许访问接口
//            return true;
//        }else { //权限不匹配。 不满足判断条件
//            throw AuthorityException.keyMismatch();
//        }
    }

    /**
     * 匹配字符串
     * @param prefix 用户权限字符串
     * @param target 接口权限字符串
     * @return 判断用户权限字符串，是否满足，目标权限字符串的前缀
     * aass对比aass_a为true
     * aass对比aass_b为true
     * aass_a对比aass_b为false
     */
    static boolean isPrefix(String prefix, String target) {
        
        if (prefix==null || prefix.isEmpty()){
            return false;
        }
        // 正则表达式
        String regex = "^" + Pattern.quote(prefix) + "(_.*)?$";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(target);


        return matcher.matches();
    }
}
